package xyz.labmem.core.util.gui.loading

import javafx.application.Platform
import javafx.concurrent.Task
import javafx.scene.layout.BorderPane
import javafx.scene.layout.Pane
import kotlinx.coroutines.*
import org.controlsfx.control.MaskerPane


/**
 * 加载框
 * @Author lty
 * @Date 2021/9/15 14:15
 */
class Loading(
    private val root: Pane
) {

    private var masker = MaskerPane()

    private var loadingRoot = BorderPane()

    init {
        masker.text = "loading.."
        loadingRoot.prefWidthProperty().bind(root.widthProperty())
        loadingRoot.prefHeightProperty().bind(root.heightProperty())
    }

    @DelicateCoroutinesApi
    fun show(): Loading {
        return show(null)
    }


    @DelicateCoroutinesApi
    fun show(back: (() -> Unit)?): Loading {
        root.children.add(loadingRoot)
        loadingRoot.center = masker
        loadingRoot.isVisible = true
        back?.let {
            GlobalScope.launch(Dispatchers.Main) {
                withContext(Dispatchers.IO) {
                    it()
                }
                hide()
            }
        }
        return this
    }

    fun hide(): Loading {
        root.children.remove(loadingRoot)
        return this
    }

    fun getMasker(back: (MaskerPane) -> Unit): Loading {
        back(masker)
        return this
    }

    @DelicateCoroutinesApi
    fun taskInit(task: Task<*>) {
        show().apply {
            masker.textProperty().bind(task.messageProperty())
        }
        task.setOnSucceeded {
            masker.textProperty().unbind()
            hide()
        }
        task.setOnFailed {
            masker.textProperty().unbind()
            hide()
        }
        task.setOnCancelled {
            masker.textProperty().unbind()
            hide()
        }
    }

    @DelicateCoroutinesApi
    fun simpleTask(task: Task<*>): Loading {
        taskInit(task)
        Thread(task).start()
        return this
    }

    @DelicateCoroutinesApi
    fun simpleFXTask(task: Task<*>): Loading {
        taskInit(task)
        Thread { Platform.runLater(task) }.start()
        return this
    }

}